import os.path

import matplotlib.pyplot as plt
import pandas as pd

from util.report_util import *
import markdown
import argparse
import yaml

plt.ioff()

def dic2obj(d):
    top = type('new', (object,), d)
    seqs = tuple, list, set, frozenset
    for i, j in d.items():
        if isinstance(j, dict):
            setattr(top, i, dic2obj(j))
        elif isinstance(j, seqs):
            setattr(top, i,
    		    type(j)(dic2obj(sj) if isinstance(sj, dict) else sj for sj in j))
        else:
            setattr(top, i, j)
    return top

def parser():
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument('-c', '--config', default='config/lidar_report_config.yaml',type=str,
                        help='config file')
    args = parser.parse_args()

    return args

def get_parameter():
    args = parser()
    with open(args.config, 'r') as f:
        config = yaml.full_load(f)
    return config

def creat_report_main(config_file = 'config/lidar_report_config.yaml'):
    with open(config_file, 'r') as f:
        config = yaml.full_load(f)
    config['output_path']=os.path.join(config['root_path'],config['output_path'])
    config['confusion_path']=os.path.join(config['output_path'],'confusion')
    config['P_R_curve'] = os.path.join(config['output_path'], 'P_R_curve')
    config['data_describe'] = os.path.join(config['output_path'], 'data_describe')
    config['report_path_name']=os.path.join(config['output_path'],config['report_name'])
    config['sum_data_path'] = os.path.join(config['output_path'], 'sum_data')
    if not os.path.exists(config['output_path']):
        os.makedirs(config['output_path'])
    if not os.path.exists(config['confusion_path']):
        os.makedirs(config['confusion_path'])
    if not os.path.exists(config['P_R_curve']):
        os.makedirs(config['P_R_curve'])
        if not os.path.exists(config['data_describe']):
            os.makedirs(config['data_describe'])
    if not os.path.exists(config['sum_data_path']):
        os.makedirs(config['sum_data_path'])
    # 指标类别
    config['indexs_type']=[]
    for target_level_indicator in config['target_level_indicators']:
        config['indexs_type'] += config['target_level_indicators'][target_level_indicator]
    config['sum_indexs_type'] = config['APS']+config['indexs_type']+config['MOT']

    # 目标匹配
    print('目标匹配...')
    object_kpi = []
    for scene in config['scene']:
        pr_data_path = os.path.join(config['root_path'], scene, config['scene'][scene]['pr_data_path'])
        pr_data_type = config['scene'][scene]['pr_data_type']
        gt_data_path = os.path.join(config['root_path'], scene, config['scene'][scene]['gt_data_path'])
        gt_data_type = config['scene'][scene]['gt_data_type']
        object_kpi+=get_target_match_data(pr_data_path,
                                          pr_data_type,
                                          gt_data_path,
                                          gt_data_type,
                                          scene,
                                          config['iou_valve'])
    object_kpi_pd=pd.DataFrame(object_kpi)
    object_kpi_pd.columns=config['headline']

    print('数据处理...')
    object_kpi_pd=data_process(object_kpi_pd)

    # 真值类型归并
    object_kpi_pd_temp=object_kpi_pd['gt_type'].to_numpy()
    for class1 in config['classes']:
        types = config['classes'][class1]
        for type in types:
            object_kpi_pd_temp[object_kpi_pd['gt_type']==type]=class1
    object_kpi_pd_temp[(object_kpi_pd['gt_type'] == 'car') & (object_kpi_pd['gt_l'] >= 8)]='truck'
    object_kpi_pd_temp[(object_kpi_pd['gt_type'] == 'truck') & (object_kpi_pd['gt_l'] <= 5)] = 'car'
    object_kpi_pd['gt_type'] = object_kpi_pd_temp
    object_kpi_pd_temp = object_kpi_pd['pr_type'].to_numpy()
    object_kpi_pd_temp[(object_kpi_pd['pr_type'] == 'car') & (object_kpi_pd['pr_l'] >= 8)]='truck'
    object_kpi_pd_temp[(object_kpi_pd['pr_type'] == 'truck') & (object_kpi_pd['pr_l'] <= 5)] = 'car'
    object_kpi_pd['pr_type']=object_kpi_pd_temp

    object_kpi_pd=object_kpi_pd.dropna()

    print('绘制相关统计图...')
    report_txt_figure = plot_evaluation_index(object_kpi_pd,config)
    print('计算各项检测指标...')
    APS_data, EEOR=compute_evaluation_index(object_kpi_pd,config)
    print('计算各项多目标跟踪指标...')
    MOTs = compute_evaluation_MOT(object_kpi_pd, config)
    print('绘制表格...')
    tables = creat_table(APS_data, EEOR, MOTs, config)
    print('生成报告...')
    reports_txt=creat_report(tables, report_txt_figure, object_kpi_pd, config)
    print('保存综合数据...')

    target_num = {"sum_target":sum(object_kpi_pd['gt_type'] != 'NULL'),'pre_num':sum((object_kpi_pd['gt_type'] != 'NULL') & (object_kpi_pd['pr_type'] != 'NULL'))}
    pd.DataFrame(target_num,index=[0]).to_csv(os.path.join(config['sum_data_path'],'目标数.csv'))
    tables['sum_indexs_type'].to_csv(os.path.join(config['sum_data_path'],'综合指标.csv'))
    tables['target_level_indicators']['all_class']['位置误差'].loc['all_scene'].to_csv(os.path.join(config['sum_data_path'],'位置误差.csv'))
    tables['target_level_indicators']['all_class']['尺寸误差'].loc['all_scene'].to_csv(os.path.join(config['sum_data_path'],'尺寸误差.csv'))
    tables['target_level_indicators']['all_class']['速度误差'].loc['all_scene'].to_csv(os.path.join(config['sum_data_path'],'速度误差.csv'))
    tables['target_level_indicators']['all_class']['加速度误差'].loc['all_scene'].to_csv(os.path.join(config['sum_data_path'],'加速度误差.csv'))

    # king
    with open(config['report_path_name']+'.md', 'w') as f:
        for i in reports_txt:
            for j in reports_txt[i]:
                f.write(j)

if __name__ == '__main__':
    # config = get_parameter()
    config_file = 'config/lidar_report_config.yaml'
    with open(config_file, 'r') as f:
        config = yaml.full_load(f)
    config['output_path']=os.path.join(config['root_path'],config['output_path'])
    config['confusion_path']=os.path.join(config['output_path'],'confusion')
    config['P_R_curve'] = os.path.join(config['output_path'], 'P_R_curve')
    config['data_describe'] = os.path.join(config['output_path'], 'data_describe')
    config['report_path_name']=os.path.join(config['output_path'],config['report_name'])
    config['sum_data_path'] = os.path.join(config['output_path'], 'sum_data')
    if not os.path.exists(config['output_path']):
        os.makedirs(config['output_path'])
    if not os.path.exists(config['confusion_path']):
        os.makedirs(config['confusion_path'])
    if not os.path.exists(config['P_R_curve']):
        os.makedirs(config['P_R_curve'])
        if not os.path.exists(config['data_describe']):
            os.makedirs(config['data_describe'])
    if not os.path.exists(config['sum_data_path']):
        os.makedirs(config['sum_data_path'])
    # 指标类别
    config['indexs_type']=[]
    for target_level_indicator in config['target_level_indicators']:
        config['indexs_type'] += config['target_level_indicators'][target_level_indicator]
    config['sum_indexs_type'] = config['APS']+config['indexs_type']+config['MOT']

    # 目标匹配
    print('目标匹配...')
    object_kpi = []
    for scene in config['scene']:
        pr_data_path = os.path.join(config['root_path'], scene, config['scene'][scene]['pr_data_path'])
        pr_data_type = config['scene'][scene]['pr_data_type']
        gt_data_path = os.path.join(config['root_path'], scene, config['scene'][scene]['gt_data_path'])
        gt_data_type = config['scene'][scene]['gt_data_type']
        object_kpi+=get_target_match_data(pr_data_path,
                                          pr_data_type,
                                          gt_data_path,
                                          gt_data_type,
                                          scene,
                                          config['iou_valve'])
    object_kpi_pd=pd.DataFrame(object_kpi)
    object_kpi_pd.columns=config['headline']

    print('数据处理...')
    object_kpi_pd=data_process(object_kpi_pd)

    # 真值类型归并
    object_kpi_pd_temp=object_kpi_pd['gt_type'].to_numpy()
    for class1 in config['classes']:
        types = config['classes'][class1]
        for type in types:
            object_kpi_pd_temp[object_kpi_pd['gt_type']==type]=class1
    object_kpi_pd_temp[(object_kpi_pd['gt_type'] == 'car') & (object_kpi_pd['gt_l'] >= 8)]='truck'
    object_kpi_pd_temp[(object_kpi_pd['gt_type'] == 'truck') & (object_kpi_pd['gt_l'] <= 5)] = 'car'
    object_kpi_pd['gt_type'] = object_kpi_pd_temp
    object_kpi_pd_temp = object_kpi_pd['pr_type'].to_numpy()
    object_kpi_pd_temp[(object_kpi_pd['pr_type'] == 'car') & (object_kpi_pd['pr_l'] >= 8)]='truck'
    object_kpi_pd_temp[(object_kpi_pd['pr_type'] == 'truck') & (object_kpi_pd['pr_l'] <= 5)] = 'car'
    object_kpi_pd['pr_type']=object_kpi_pd_temp

    object_kpi_pd=object_kpi_pd.dropna()

    print('绘制相关统计图...')
    report_txt_figure = plot_evaluation_index(object_kpi_pd,config)
    print('计算各项检测指标...')
    APS_data, EEOR=compute_evaluation_index(object_kpi_pd,config)
    print('计算各项多目标跟踪指标...')
    MOTs = compute_evaluation_MOT(object_kpi_pd, config)
    print('绘制表格...')
    tables = creat_table(APS_data, EEOR, MOTs, config)
    print('生成报告...')
    reports_txt=creat_report(tables, report_txt_figure, object_kpi_pd, config)
    print('保存综合数据...')

    target_num = {"sum_target":sum(object_kpi_pd['gt_type'] != 'NULL'),'pre_num':sum((object_kpi_pd['gt_type'] != 'NULL') & (object_kpi_pd['pr_type'] != 'NULL'))}
    pd.DataFrame(target_num,index=[0]).to_csv(os.path.join(config['sum_data_path'],'目标数.csv'))
    tables['sum_indexs_type'].to_csv(os.path.join(config['sum_data_path'],'综合指标.csv'))
    tables['target_level_indicators']['all_class']['位置误差'].loc['all_scene'].to_csv(os.path.join(config['sum_data_path'],'位置误差.csv'))
    tables['target_level_indicators']['all_class']['尺寸误差'].loc['all_scene'].to_csv(os.path.join(config['sum_data_path'],'尺寸误差.csv'))
    tables['target_level_indicators']['all_class']['速度误差'].loc['all_scene'].to_csv(os.path.join(config['sum_data_path'],'速度误差.csv'))
    tables['target_level_indicators']['all_class']['加速度误差'].loc['all_scene'].to_csv(os.path.join(config['sum_data_path'],'加速度误差.csv'))

    # king
    with open(config['report_path_name']+'.md', 'w') as f:
        for i in reports_txt:
            for j in reports_txt[i]:
                f.write(j)


# run lidar_report.py -c config/lidar_report_config.yaml